﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Utilities
{
    /// <summary>
    /// 迈点光源控制器
    /// </summary>
    public class MaiDianController
    {
        private System.IO.Ports.SerialPort serialport = new System.IO.Ports.SerialPort();

        private bool blnRun = true;
        private System.Threading.Thread _thread;

        public void Start()
        {
            _thread = new System.Threading.Thread(new ThreadStart(threadFunction));
            _thread.IsBackground = true;
            _thread.Start();
        }

        public void Quit()
        {
            blnRun = false;
        }
 
        private void threadFunction()
        {
 
            while(blnRun)
            {
                pollingFunction();
                System.Threading.Thread.Sleep(10);

 
            }
        }

        /// <summary>
        /// 0: 初始化连接
        /// 10：连线
        /// 20：故障
        /// </summary>
        int statusCode = 0;

        private void pollingFunction()
        {
            try
            {
                switch (statusCode)
                {
                    case 0:

                        if (OpenConnect())
                        {
                            statusCode = 10;
                        }
                        else
                        {
                            System.Threading.Thread.Sleep(5000);
                        }

                        break;
                    case 10:
                        ProcessCmd();
 
                        break;
                    case 20:

                        statusCode = 0;

                        break;
                }
            }
            catch ( Exception ex)
            {

            }
        }
        SafeQueue<string> Q_Cmd = new SafeQueue<string>();
        public void OffLight()
        {
            for (int i = 0; i < 4; i++)
            {
                SetLight(0,i);
            }
        }
        public void SetLight(string cmd)
        {
            Q_Cmd.Enqueue(cmd);
        }
        public void SetLight(int Power,int Channel)
        {
            string cmd = "";//SA{0}#SB{1}#SC{2}#SD{3}#
            switch (Channel)
            {
                case 0:
                    cmd = "SA";
                    break;
                case 1:
                    cmd = "SB";
                    break;
                case 2:
                    cmd = "SC";
                    break;
                case 3:
                    cmd = "SD";
                    break;
                default:
                    cmd = "";
                    break;

            }
            if (cmd=="")
            {
                return;

            }
            cmd = cmd + Power.ToString().PadLeft(4, '0') + "#";
            Q_Cmd.Enqueue(cmd);
        }
        private void ProcessCmd()
        {
            //if(flagCh1Light )
            //{
            //    SetChannelLight(intCh1Light, intCh2Light, intCh3Light, intCh4Light);
            //    flagCh1Light = false;
            //    System.Threading.Thread.Sleep(500);
            //}

            if (Q_Cmd.Count>0)
            {
                string cmd = Q_Cmd.Dequeue();

                if (bConnected == false)
                {
                    System.Windows.Forms.MessageBox.Show("ligth controller disconnected");
                    return;
                }
                try
                {
                    //24V 光源控制器
                    string strCh1On = true ? "T" : "F";
                    //string strCh2On = ch2On ? "T" : "F";
                    string strsend1 = string.Format("S{0}{1}C#", 255.ToString().PadLeft(3, '0'), strCh1On);

                    // 5V 光源控制器
                    string strsend = cmd;

                    serialport.DiscardInBuffer();
                    serialport.DiscardOutBuffer();
                    serialport.Write(strsend);
                    System.Threading.Thread.Sleep(200);
                    string str = serialport.ReadExisting();

                }
                catch (Exception ex)
                {
                    Log(ex.Message);
                }


            }
 
        }


        #region 外部开放
 
        int intCh1Light = 0;
        int intCh2Light = 0;

        int intCh3Light = 0;
        int intCh4Light = 0;

        bool CH1OnOff = true;
        bool CH2OnOff = true;

        bool flagCh1Light = false;

        public void SetLight(int ch1Light, int ch2light, int ch3Light, int ch4Light)
        {
            intCh1Light = ch1Light;
            intCh2Light = ch2light;
            intCh3Light = ch3Light;
            intCh4Light = ch4Light;

            flagCh1Light = true;
        }
 

        #endregion

        private bool bConnected  = false;

        private MaiDianController()
        { }

        /// <summary>
        /// 默认通信超时 1000ms
        /// </summary>
        /// <param name="PortName">串口名称：</param>
        /// <param name="BaudRate">波特率: 默认9600</param>
        /// <param name="DataSize">数据位: 默认 8</param>
        /// <param name="Parity">校验位: 默认 None</param>
        /// <param name="StopBits">停止位: 默认 One</param>
        public MaiDianController(string PortName , int BaudRate=19200, int DataSize = 8 , System.IO.Ports.Parity Parity = System.IO.Ports.Parity.None,
                                    System.IO.Ports.StopBits StopBits = System.IO.Ports.StopBits.One)
        {
            bConnected = false;
            serialport.PortName = PortName;
            serialport.BaudRate = BaudRate;
            serialport.DataBits = DataSize;
            serialport.Parity = Parity;
            serialport.StopBits = StopBits;

            serialport.ReadTimeout = 1000;
        }
        /// <summary>
        /// 控制器串口通信设定
        /// </summary>
        /// <param name="PortName"></param>
        /// <param name="BaudRate"></param>
        /// <param name="DataSize"></param>
        /// <param name="Parity"></param>
        /// <param name="StopBits"></param>
        public void PortConfig(string PortName, int BaudRate = 9600, int DataSize = 8, System.IO.Ports.Parity Parity = System.IO.Ports.Parity.None,
                            System.IO.Ports.StopBits StopBits = System.IO.Ports.StopBits.One)
        {
            DisConnect();
            bConnected = false;
            serialport.PortName = PortName;
            serialport.BaudRate = BaudRate;
            serialport.DataBits = DataSize;
            serialport.Parity = Parity;
            serialport.StopBits = StopBits;
            serialport.ReadTimeout = 1000;
        }

        public bool OpenConnect()
        {
            try
            {
 
                serialport.Open();
                //serialport.DiscardOutBuffer();
                //serialport.DiscardInBuffer();

                bConnected = true;

            }
            catch(Exception ex)
            {
                Log(ex.Message);
                return false;
            }
            return true;
        }

 
        /// <summary>
        /// 关闭串口
        /// </summary>
        public void DisConnect()
        {
            if(serialport.IsOpen)
            {
                serialport.Close();
            }
        }

        /// <summary>
        /// 设置通道亮度
        /// </summary>
        /// <param name="Ch1">通道1 亮度值： 0 - 255</param>
        /// <param name="Ch2">通道2 亮度值： 0 - 255 </param>
        private void SetChannelLight(int Ch1, int Ch2, int Ch3, int Ch4)
        {
            if(bConnected== false)
            {
                System.Windows.Forms.MessageBox.Show("ligth controller disconnected");
                return;
            }
            try
            { 
                // 24V 光源控制器
                //string strCh1On = ch1On?"T":"F";
                //string strCh2On = ch2On?"T":"F";
                //string strsend = string.Format("S{0}{1}{2}{3}C#", Ch1.ToString().PadLeft(3, '0'), strCh1On, Ch2.ToString().PadLeft(3, '0'), strCh2On);

                // 5V 光源控制器
                string strsend = string.Format("SA{0}#SB{1}#SC{2}#SD{3}#", Ch1.ToString().PadLeft(4, '0'), Ch2.ToString().PadLeft(4, '0'),
                                        Ch3.ToString().PadLeft(4, '0'), Ch4.ToString().PadLeft(4, '0')
                                    );

                serialport.DiscardInBuffer();
                serialport.DiscardOutBuffer();
                serialport.Write(strsend);
                System.Threading.Thread.Sleep(200);
                string str = serialport.ReadExisting();
            }
            catch(Exception ex)
            {
                Log(ex.Message);
            }
        }

        /// <summary>
        /// 设置通道亮度延时
        /// </summary>
        /// <param name="Ch">通道</param>
        /// <param name="delay">光源常亮持续时间</param>
        private void SetChannelDelay(int Ch, int delay)
        {
            if(bConnected== false)
            {
                System.Windows.Forms.MessageBox.Show("ligth controller disconnected");
                return;
            }
            try
            {
                byte[] channelSetting = new byte[] { 0xFF, 0xA2, 0x01, 0x03, 0x00, 0x00, 0xFE };
                switch (Ch)
                {
                    case 1:
                        channelSetting[2] = 1;
                        channelSetting[4] = (byte)(delay / 256);
                        channelSetting[5] = (byte)(delay % 256);
                        serialport.Write(channelSetting, 0, 7);
                        break;
                    case 2:
                        channelSetting[2] = 2;
                        channelSetting[4] = (byte)(delay / 256);
                        channelSetting[5] = (byte)(delay % 256);
                        serialport.Write(channelSetting, 0, 7);
                        break;
                }
            }
            catch(Exception ex)
            {
                Log(ex.Message);
            }
        }

        /// <summary>
        /// 获取光源控制器当前设定
        /// </summary>
        /// <param name="Ch1Light">通道1亮度</param>
        /// <param name="Ch1Delay">通道1延时</param>
        /// <param name="Ch2Light">通道2亮度</param>
        /// <param name="Ch2Delay">通道2延时</param>
        public void GetSettingValue(out int Ch1Light, out int Ch1Delay, out int Ch2Light, out int Ch2Delay)
        {
            Ch1Light = 0;
            Ch2Light = 0;
            Ch1Delay = 0;
            Ch2Delay = 0;

            serialport.DiscardInBuffer();
            serialport.DiscardOutBuffer();

            byte[] getsetting = new byte[] { 0xFF, 0xA2, 0x00, 0x0D, 0x00, 0x00, 0xFE };
            serialport.Write(getsetting, 0, 7);
            System.Threading.Thread.Sleep(200);
            int count = serialport.ReadBufferSize;
            byte[] bRecv = new byte[count];
            count = serialport.Read(bRecv, 0, count);

            if(count != 14)
            {
                return;
            }

            Ch1Light = bRecv[3];
            Ch2Light = bRecv[10];

            Ch1Delay = bRecv[5] + bRecv[4] * 256;
            Ch2Delay = bRecv[12] + bRecv[11] * 256;
        }

        /// <summary>
        /// 保存所有设定
        /// </summary>
        private void SaveSettings()
        {
            if(bConnected== false)
            {
                System.Windows.Forms.MessageBox.Show("ligth controller disconnected");
                return;
            }
            try
            {
                byte[] SaveSettings = new byte[] { 0xFF, 0xA2, 0x00, 0x05, 0x00, 0x00, 0xFE };
                serialport.Write(SaveSettings, 0, 7);
            }
            catch(Exception ex)
            {
                Log(ex.Message);
            }

        }

        public Action<string> LOG = null;
        void Log(string s)
        {
            if (LOG != null)
            {
                LOG(s);
            }
            //LogHelper.Write(Utilities.Module.Motion, name + " :" + s);
        }
    }


    /*
    public class MDControler_TCP
    {
        TcpClient client = new TcpClient();
        IPEndPoint remotePoint;

        string name = "";
        bool isRun = false;
        int channelCount = 0;
        Thread cmdThread;
        SafeQueue<SetCMD> queueCMD = new SafeQueue<SetCMD>();
        List<int> brightness = new List<int>();
        char[] channelUpperCMD = { 'A', 'B', 'C', 'D' };
        char[] channelLowerCMD = { 'a', 'b', 'c', 'd' };

        public MDControler_TCP(string vRemoteIP, int vRemotePort, string vName, int vChannelCount = 2)
        {
            remotePoint = new IPEndPoint(IPAddress.Parse(vRemoteIP), vRemotePort);
            name = vName;
            channelCount = vChannelCount;
            for (int i = 0; i < channelCount; i++)
            {
                brightness.Add(0);
            }
        }

        public void Start()
        {
            isRun = true;
            cmdThread = new Thread(ThreadFunc);
            cmdThread.IsBackground = true;
            cmdThread.Start();
        }

        public void Quit()
        {
            isRun = false;
        }

        public bool Connect()
        {
            try
            {
                client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 500);
                client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 500);
                if (!client.Client.Connected)
                {
                    client.Client.Connect(remotePoint);
                }
                return true;
            }
            catch (Exception ex)
            {
                //Log
                //MessageBox.Show(ex.Message);
                return false;
            }
        }
        private void Disconnect()
        {
            try
            {
                if (client.Client.Connected)
                {
                    client.Close();
                }
            }
            catch (Exception ex)
            {
                //Log
            }
        }

        private void ThreadFunc()
        {
            int tStatus = 0;
            while (isRun)
            {
                switch (tStatus)
                {
                    case 0:
                        if (Connect())
                        {
                            tStatus = 1;
                        }
                        else
                        {
                            Thread.Sleep(5000);
                        }
                        break;

                    case 1:
                        if (!CMDFunc())
                        {
                            tStatus = 0;
                        }
                        break;

                    default:
                        tStatus = 0;
                        break;

                }
                Thread.Sleep(200);
            }

            Disconnect();
        }

        private bool CMDFunc()
        {
            try
            {
                //写命令
                if (queueCMD.Count > 0)
                {
                    SetCMD tSetCMD = queueCMD.Dequeue();
                    byte[] tSendData = ASCIIEncoding.ASCII.GetBytes(tSetCMD.cmd);
                    client.Client.Send(tSendData, tSendData.Length, SocketFlags.None);
                    byte[] tReciveData = new byte[512];
                    int tCount = client.Client.Receive(tReciveData);
                    string tReturnData = ASCIIEncoding.ASCII.GetString(tReciveData).Trim();
                    if (!tReturnData.Contains(tSetCMD.confirm))//如果不包含返回字母
                    {
                        //Log
                    }
                    Thread.Sleep(200);
                }

                //读命令
                for (int i = 0; i < channelCount; i++)
                {
                    byte[] tSendData = ASCIIEncoding.ASCII.GetBytes("S" + channelUpperCMD[i] + "#");
                    client.Client.Send(tSendData, tSendData.Length, SocketFlags.None);
                    byte[] tReciveData = new byte[512];
                    int tCount = client.Client.Receive(tReciveData);
                    string tReturnData = ASCIIEncoding.ASCII.GetString(tReciveData).Trim();

                    if (tReturnData.Contains(channelLowerCMD[i]))
                    {
                        int tIdx = tReturnData.IndexOf(channelLowerCMD[i]);
                        int tVal = 0;
                        if (int.TryParse(tReturnData.Substring(tIdx + 1, 4), out tVal))
                        {
                            brightness[i] = tVal;
                        }
                    }
                    else
                    {
                        //Log
                    }
                    Thread.Sleep(200);
                }

                return true;
            }
            catch (Exception ex)
            {
                //Log
                return false;
            }
        }

        public int GetBrightness(int vChannel)
        {
            if (vChannel < 1) return -1;
            return brightness[vChannel - 1];
        }

        public void SetBrightness(int vChannel, int vBrightness)
        {
            int tBrightness = vBrightness;
            if (vChannel < 1 || vChannel > 4) return;
            if (vBrightness < 0) tBrightness = 0;
            if (vBrightness > 255) tBrightness = 255;
            string tCMD = "S" + channelUpperCMD[vChannel - 1] + string.Format("{0:0000}#", tBrightness);
            queueCMD.Enqueue(new SetCMD(tCMD, channelUpperCMD[vChannel - 1]));
        }

        class SetCMD
        {
            public string cmd;
            public char confirm;
            public SetCMD()
            {

            }
            public SetCMD(string vCMD, char vConfirm)
            {
                cmd = vCMD;
                confirm = vConfirm;
            }
        }
    }
    */
}
